package com.yzd.learnjava.concurrency;

import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import com.yzd.learnjava.util.Print;

public class Interrupting {
	private static ExecutorService exec = Executors.newCachedThreadPool();
	static void test(Runnable runnable) throws InterruptedException {
		Future<?> f = exec.submit(runnable);
		TimeUnit.MILLISECONDS.sleep(100);
		Print.print("Interupting " + runnable.getClass().getSimpleName());
		f.cancel(true);
		Print.print("Interupt sent to " + runnable.getClass().getSimpleName());
		
	}
	
	public static void main(String[] args) throws InterruptedException {
		test(new SleepBlocked());
		test(new IOBlocked(System.in));
		test(new SynchronizedBlocked());
		TimeUnit.SECONDS.sleep(3);
		Print.print("Aborting with System.exit(0)");
		System.exit(0);
	}
}

class SleepBlocked implements Runnable{
	public void run() {
		try {
			TimeUnit.SECONDS.sleep(100);
		} catch (InterruptedException e) {
			Print.print("InterruptedException");
		}
		
		Print.print("Exiting SleepBlocked.run()");
	}
}

class IOBlocked implements Runnable{
	private InputStream in ;
	public IOBlocked(InputStream in) {
		this.in = in;
	}
	public void run() {
		try {
			Print.print("Waitting for read");
			in.read();
		} catch (IOException e) {
			if(Thread.currentThread().isInterrupted()) {
				Print.print("Interupted from blockde IO");
			} else {
				throw new RuntimeException();
			}
		}
		Print.print("exiting IOBlocked.run()");
	}
}

class SynchronizedBlocked implements Runnable{
	public synchronized void f() {
		while(true) {
			Thread.yield();
		}
	}
	
	public SynchronizedBlocked() {
		new Thread(){
			public void run() {
				f();
			}
		}.start();
	}
	
	public void run() {
		Print.print("trying to call f()");
		f();
		Print.print("Exiting SynchronizedBlocked.run()");
	}
}






















